<template>
  <!-- 评论区 -->
  <view class="comments-container">
    <!-- 评论数量 -->
    <view class="comments-num">评论（{{commentNum}}条）</view>
    <!-- 无评论时 -->
    <view v-if="mainCommentsData.dataStatus=='empty'&&commentNum==0">
      <data-empty description="快来抢沙发吧~" />
    </view>
    <!-- 有评论时 -->
    <block v-for="(item,index) in mainCommentsData.data" :key="item[props.commentId]">
      <!-- 主评论 -->
      <view class="main-comments comment-container">
        <!-- 左侧头像 -->
        <view class="left-container" @click="handleclickUserAvatar(item)">
          <image class="user-avatar" :src="item[props.avatar]"></image>
        </view>
        <!-- 右侧 -->
        <view class="right-container">
          <!-- 评论头信息区域 -->
          <view class="head-container">
            <view class="user-info-container">
              <text>{{item[props.userName]}}</text>
              <view v-if="item[props.userId] == creatorUserId" class="author">
                <text>作者</text>
              </view>
            </view>
            <view class="like-container" @click="handleLikeComment(item)">
              <uni-icons class="icon" custom-prefix="iconfont" type="icon-like"
                :color="item[props.likeStatus]?'#3fd3d1':'#a2a2a2'" size="32rpx">
              </uni-icons>
              <text class="like-num">{{item[props.likeNum]?item[props.likeNum]:0}}</text>
            </view>
          </view>

          <!-- 评论内容区域 -->
          <view class="comment-contet-container" @longtap="handleLongtapRemoveComment(item,0)">
            <text>{{item[props.content]}}</text>
          </view>
          <!-- 评论时间与回复 -->
          <view class="comment-date-container">
            <text>{{ item[props.createTime]|filterDateDiff}}</text>
            <text @click="handleReplyComment(item,item)">回复</text>
          </view>
        </view>

      </view>

      <block v-if="childCommentsData[item[props.commentId]]&&childCommentsData[item[props.commentId]].open">
        <!-- 二级评论 -->
        <view class="child-comments comment-container"
          v-for="(item2,cidx) in childCommentsData[item[props.commentId]].data" :key="item2[props.commentId]">
          <view class="left-container" @click="handleclickUserAvatar(item2)">
            <image class="user-avatar" :src="item2[props.avatar]"></image>
          </view>
          <view class="right-container">
            <view class="head-container">
              <view class="user-info-container">
                <text>{{item2[props.userName]}}</text>
                <view v-if="item2[props.userId] == creatorUserId" class="author">
                  <text>作者</text>
                </view>
              </view>
              <view class="like-container" @click="handleLikeComment(item2,item)">
                <uni-icons class="icon" custom-prefix="iconfont" type="icon-like"
                  :color="item2[props.likeStatus]?'#3fd3d1':'#a2a2a2'" size="32rpx">
                </uni-icons>
                <text class="like-num">{{item2[props.likeNum]?item2[props.likeNum]:0}}</text>
              </view>
            </view>
            <!-- 内容 -->
            <view class="comment-contet-container" @longtap="handleLongtapRemoveComment(item2,1,item)">
              <text>回复</text>
              <text class="user-name">{{item2[props.wasRepliedName]}}:</text>
              <text>{{item2[props.content]}}</text>
            </view>
            <!-- 评论时间 -->
            <view class="comment-date-container" @click="handleReplyComment(item2,item)">
              <text>{{ item2[props.createTime]|filterDateDiff(true)}}</text>
              <text>回复</text>
            </view>
          </view>
        </view>
        <!-- <view class="status-container"> -->
        <!-- <text v-if="childCommentsData[item[props.commentId]].reqStatus=='loading'">加载中</text> -->
        <!-- <block v-if="childCommentsData[item[props.commentId]].reqStatus=='done'"> -->
        <!-- <text v-if="childCommentsData[item[props.commentId]].dataStatus=='load-more'"
              @click="handleGetChildCommentList(item)">点击加载更多</text> -->
        <!-- <text v-if="childCommentsData[item[props.commentId]].dataStatus=='no-more'">已全部加载完成</text> -->
        <!-- </block> -->
        <!-- </view> -->
      </block>

      <block v-if="item[props.commentsNum]">
        <view class="more-open-container">
          <view>
            <view
              v-if="!(childCommentsData[item[props.commentId]]&&childCommentsData[item[props.commentId]].open)||childCommentsData[item[props.commentId]].dataStatus=='load-more'"
              @click="handleOpenChildList(item,true,childCommentsData[item[props.commentId]]&&childCommentsData[item[props.commentId]].open)"
              class="more-comment">
              <view class="divider"></view>
              <text
                v-if="!(childCommentsData[item[props.commentId]]&&childCommentsData[item[props.commentId]].open)">展开{{item.commentsNum}}条回复</text>
              <text
                v-if="(childCommentsData[item[props.commentId]]&&childCommentsData[item[props.commentId]].open)&&childCommentsData[item[props.commentId]].dataStatus=='load-more'">加载更多</text>
              <uni-icons class="icon" custom-prefix="iconfont" type="icon-back" color="#a2a2a2" size="28rpx">
              </uni-icons>
            </view>
          </view>
          <view>
            <view v-if="(childCommentsData[item[props.commentId]]&&childCommentsData[item[props.commentId]].open)"
              @click="handleOpenChildList(item,false)" class="more-comment more-comment-expand">
              <text>收起评论</text>
              <uni-icons class="icon" custom-prefix="iconfont" type="icon-back" color="#a2a2a2" size="28rpx">
              </uni-icons>
            </view>
          </view>

        </view>
      </block>
    </block>
    <view class="status-container">
      <text v-if="mainCommentsData.reqStatus=='loading'">加载中</text>
      <block v-else-if="mainCommentsData.reqStatus=='done'">
        <text v-if="mainCommentsData.dataStatus=='load-more'" @click="handleGetMainCommentList(false)">点击加载更多</text>
        <text v-else-if="mainCommentsData.dataStatus=='no-more'">已全部加载完成</text>
      </block>
    </view>

    <!-- 输入框 -->
    <view class="comments-post-container"
      :style="{bottom:postInputData.bottom+'px','padding-bottom':postInputData.safeAreaBottom}">
      <view class="left-container">
        <view class="input-container">
          <input cursor-spacing="10px" type="text" v-model.trim="postCommentData.content" @blur="handleInputBlur"
            @focus="handleInputFocus" :focus="postInputData.inputFocus" always-embed :adjust-position="false"
            :placeholder="postInputData.placeholder" maxlength="36" />
        </view>
      </view>
      <!-- 按钮 -->
      <view class="right-container">
        <view class="post-btn" @click="handleSendCommentFunc">
          <text>发送</text>
        </view>
      </view>
    </view>


  </view>

</template>

<script>
  import CertifiedMixin from "@/plugins/certified.js"
  export default {
    mixins: [CertifiedMixin],
    name: "common-comments",
    props: {
      // 评论数
      commentNum: {
        type: String | Number,
        default: 0
      },
      // 发布者用户id
      creatorUserId: {
        type: String,
        default: ''
      },
      // 当前用户id
      currentUserId: {
        type: String,
        default: ''
      },
      // 配置 名:封装组件中，需要与业务进行解耦。
      // 一是采用指定组件数据结构，由父组件需要对数据进行处理满足封装组件，过程较为繁琐。
      // 二是增加配置，通过配置处理进行数据关系映射，既不影响封装组件的逻辑处理，进而减少父组件针对封装组件的修改成本。
      props: {
        type: Object,
        default: () => {
          return {
            // 评论内容
            content: 'content',
            // 用户头像
            avatar: "avatar",
            // 评论主键
            commentId: "commentId",
            // 评论下的子评论数
            commentsNum: "commentsNum",
            // 发布时间
            createTime: "createTime",
            // 点赞数量
            likeNum: 'likeNum',
            // 点赞状态
            likeStatus: "likeStatus",
            // 发布者用户id
            userId: "userId",
            // 发布者昵称
            userName: "userName",
            // 被回复用户昵称
            wasRepliedName: 'wasRepliedName',
          }
        }
      },
      // 名：将数据加载与处理事件，交由父级处理，减少耦合度。【这里需要豪哥加词了~】
      // 加载主评论数据
      loadMainCommentData: {
        type: Function,
        default: () => {}
      },
      // 加载子评论数据
      loadChildCommentData: {
        type: Function,
        default: () => {}
      },
      // 删除评论数据
      removeCommentData: {
        type: Function,
        default: () => {}
      },
      // 发送评论数据
      sendCommentData: {
        type: Function,
        default: () => {}
      },
      // 点赞评论
      likeComment: {
        type: Function,
        default: () => {}
      },
    },
    data() {
      return {
        // 主评论数据
        mainCommentsData: {
          // 当前页数
          page: 0,
          // 请求状态 空 loading done
          reqStatus: '',
          // 数据状态 load-more no-more empty
          dataStatus: 'load-more',
          // 评论数据
          data: [],
        },
        // 子评论数据  子评论的 key为主评论主键 value的结构相比mainCommentsData一致，增加了open-是否展开子评论列表 parentID-表示主评论关联主键
        childCommentsData: {},
        // 发布评论关联数据
        postCommentData: {
          // 评论内容
          content: '',
          // 评论类型 0-主评论 1-回复评论
          type: 0,
          // 被回复的评论信息
          data: null,
          // 被回复评论的一级评论信息
          mainData: null
        },
        // 输入框属性
        postInputData: {
          // 焦点状态
          inputFocus: false,
          // 输入框距离底部距离
          safeAreaBottom: 0,
          bottom: 0,
          // 输入框提示信息
          placeholder: '请输入评论内容',
        },
      };
    },
    mounted() {
      this.handleGetMainCommentList(true);
      // 获取安全区域
      let sysinfo = uni.getSystemInfoSync();
      let c = sysinfo.screenHeight - sysinfo.safeArea.bottom;
      if (c != 0) {

        this.postInputData.safeAreaBottom = Math.max(uni.upx2px(48), c) + 'px'
      } else {
        this.postInputData.safeAreaBottom = '48rpx'
      }

    },

    methods: {
      // 获取主评论列表
      handleGetMainCommentList(bool = false) {
        this.handlePagingData(this.mainCommentsData, 'loadMainCommentData', bool);
      },
      // 获取子评论列表
      handleGetChildCommentList(data, bool = false) {
        let parentID = data[this.props.commentId];
        this.handleCreateChildCommentData(parentID);
        this.handlePagingData(this.childCommentsData[parentID], 'loadChildCommentData', bool, data);

      },
      // 创建子评论数据
      handleCreateChildCommentData(parentID) {
        // 如果childCommentsData不存在关联parentID的数据 则需创建
        if (!this.childCommentsData[parentID]) {
          let data = {
            // 当前页数
            page: 0,
            // 请求状态 空 loading done
            reqStatus: '',
            // 数据状态 load-more no-more empty
            dataStatus: 'load-more',
            // 评论数据
            data: [],
            // 是否展开子评论
            open: false,
            // 主评论关联主键
            parentID: parentID
          }
          this.$set(this.childCommentsData, parentID, data);
        }
      },
      // 用户点击评论发布者头像
      handleclickUserAvatar(data) {
        this.$emit('clickUserAvatar', data)
      },
      // 长按删除评论 data-评论信息  type：0-代表主评论删除 1-代表子评论删除 mainData-表示主评论信息
      handleLongtapRemoveComment(data, type = 0, mainData = null) {
        // 如果评论非当前用户创建，则禁止删除操作
        if (this.currentUserId != data[this.props.userId]) {
          console.log("非当前用户评论");
          return;
        }
        uni.showModal({
          title: '提示',
          content: '是否删除该评论',
          success: async (res) => {
            if (res.confirm) {
              let {
                success
              } = await this.removeCommentData.call(this.$parent, data);
              if (success) {
                // 进行删除操作
                if (type == 0) {
                  let commentId = data[this.props.commentId]
                  let index = this.mainCommentsData.data.findIndex((item) => item[this.props.commentId] ==
                    commentId);
                  if (index != -1) {
                    this.mainCommentsData.data.splice(index, 1);
                  }
                  this.$delete(this.childCommentsData, commentId);
                } else if (type == 1) {
                  let mainData_commentId = mainData[this.props.commentId]
                  let commentId = data[this.props.commentId];
                  let index = this.childCommentsData[mainData_commentId].data.findIndex((item) => item[this
                    .props
                    .commentId] == commentId);
                  if (index != -1) {
                    this.childCommentsData[mainData_commentId].data.splice(index, 1);
                  }
                }
              }
            }
          }
        });
      },
      // 展开或收起子评论列表 data-为评论信息 bool为是否展开 ext-是否已经展开了
      handleOpenChildList(data, bool = false, ext = false) {

        if (bool) {

          this.handleGetChildCommentList(data, !ext)
        }
        this.childCommentsData[data[this.props.commentId]].open = bool;

      },
      // 输入框聚焦 
      handleInputFocus(e) {
        // scroll-view ios会下拉白屏  禁止下拉 scroll-view页面滚动
        // 名：因当前页面使用了自定义导航，固定高度scroll-view，默认输入框获取焦点，键盘拉起，上推页面，
        // 则整个页面上移，排版布局错乱，故而采用放弃上推页面，聚焦后获取键盘高度的方式过渡输入框内容位置
        // 获取键盘高度，h5不支持，h5平台无需担心键盘拉起后位移问题，输入框区域位移距离底部0像素，键盘拉起同样是在键盘上方。
        // adjust-position="false"
        let height = 0;
        // #ifdef MP-WEIXIN
        if (e && e.detail) {
          // 知识点:输入框聚焦时触发，event.detail = { value, height }，height 为键盘高度
          height = e.detail.height;
        }
        // #endif
        this.postInputData.bottom = height;
      },
      // 输入框失焦
      handleInputBlur() {
        this.postInputData.bottom = 0;
        this.postInputData.inputFocus = false;
        // 如果输入框文本内容为空，则将评论对象初始化为“文章”，否则不做任何操作，即保留当前未发布的评论信息
        if (!this.postCommentData.content) {
          this.handleSetPostCommentData();
        }
      },
      // 点击回复事件
      handleReplyComment(data, mainData = null) {
        // 如果当前评论的对象与上次评论对象不一值，清空输入框文本内容，重新设置评论对象，否则不做任何操作
        if (data[this.props.commentId] != this.postCommentData[this.props.commentId]) {
          this.handleClearContent();
          this.handleSetPostCommentData(data, mainData);
        }
        this.postInputData.inputFocus = true;
      },
      // 设置评论对象
      // 发布一级评论：data-null mainData-null
      // 回复一级评论：data-评论对象 mainData-null
      // 回复子评论：data-评论对象 mainData-一级评论对象
      handleSetPostCommentData(data = null, mainData = null) {
        let name = data ? data[this.props.userName] : '';
        this.postCommentData.data = data ? data : null;
        this.postCommentData.type = data ? 1 : 0;
        this.postInputData.placeholder = name ? `回复:${name}` : `请输入评论内容`
        this.postCommentData.mainData = mainData ? mainData : null;
      },
      // 清空输入框文本内容
      handleClearContent() {
        this.postCommentData.content = '';
      },
      handleSendCommentFunc() {
        this.handleCertified(() => {
          this.handleSendComment();
        }, "发布评论 请先认证")
      },
      // 发布评论
      async handleSendComment() {
        if (!this.postCommentData.content) {
          uni.showToast({
            title: '评论不能为空',
            duration: 1000,
            icon: 'none'
          });
          return;
        }
        let {
          success,
          data,
          message
        } = await this.sendCommentData.call(this.$parent, this.postCommentData);
        if (!success) {
          uni.showToast({
            title: message,
            icon: 'none'
          })
          return;
        }
        // 发布成功后 将新发布的评论数据添加到最前面
        if (this.postCommentData.type == 0) {
          this.mainCommentsData.data.unshift(data);
        } else if (this.postCommentData.type == 1 && this.postCommentData.mainData) {
          let commentIdKey = this.props.commentId;
          let commentId = this.postCommentData.mainData[commentIdKey];
          if (!this.childCommentsData[commentId]) {
            this.handleCreateChildCommentData(commentId);
          }
          let find = this.mainCommentsData.data.find((item) => {
            return item[commentIdKey] == commentId
          })
          find && find[this.props.commentsNum]++;
          // 二级评论的首次发布+
          if (!this.childCommentsData[commentId].open) {
            // ，没有展开的情况下 执行展开
            this.handleOpenChildList(find, true);
          } else {
            this.childCommentsData[commentId].data.unshift(data);
          }


        }
        this.$nextTick(() => {
          this.handleSetPostCommentData();
          this.handleClearContent();
        })

      },
      // 评论点赞
      async handleLikeComment(data, mainData = null) {
        let {
          success,
          status,
          likeNum
        } = await this.likeComment.call(this.$parent, data);
        if (!success) {
          return;
        }
        let commentIdKey = this.props.commentId;
        let likeStatusKey = this.props.likeStatus;
        let likeNumKey = this.props.likeNum;
        if (mainData) {
          let commentId = mainData[commentIdKey];
          let index = this.childCommentsData[commentId].data.findIndex((item) => item[commentIdKey] == data[
            commentIdKey]);
          if (index != -1) {
            this.childCommentsData[mainData[commentIdKey]].data[index][likeStatusKey] = status;
            this.childCommentsData[mainData[commentIdKey]].data[index][likeNumKey] = likeNum;
          }
        } else {
          let index = this.mainCommentsData.data.findIndex((item) => {
            console.log(item);
            return item[commentIdKey] == data[commentIdKey]
          });
          if (index != -1) {
            this.mainCommentsData.data[index][likeStatusKey] = status;
            this.mainCommentsData.data[index][likeNumKey] = likeNum;
          }
        }
      },
      // 处理分页数据通用方法
      // 因获取主评论列表与子评论列表的分页逻辑相同 所以将分页获取逻辑进行了通用封装
      // ProxyObject-代理对象 loadDataName-加载数据处理方法名称  init-是否首页加载 ext-额外参数
      async handlePagingData(ProxyObject, loadDataName = '', init = false, ext = {}) {
        if (ProxyObject.reqStatus == 'loading') {
          return
        }
        init = ProxyObject.page + 1 == 1;
        if (init) {
          // 加载首页 设置页数参数为1
          ProxyObject.page = 0;
        } else {
          // 已获取全部数据或数据为空状态下 禁止加载下一页
          if (ProxyObject.dataStatus != 'load-more') {
            return;
          }

        }
        // 如何处理方法不存在，处理方法类型不为function，则禁止加载下一页
        if (!this[loadDataName]) {
          return;
        }
        ProxyObject.reqStatus = 'loading';
        // 设置状态为加载中
        let {
          success,
          data,
          pages
        } = await this[loadDataName].call(this.$parent, {
          page: ProxyObject.page + 1,
          ext: ext
        });
        // 因作用域问题 所以使用call改变作用域为父级实例
        if (success) {
          ProxyObject.pages = pages;
          ProxyObject.page++;

        }
        if (init) {
          // 首页加载 数据采用直接赋值方式，并且设置init为true，标识已加载过首页
          ProxyObject.data = data;
        } else {
          // 非首页加载 数据采用追加的方式
          ProxyObject.data.push(...data);
        }
        ProxyObject.reqStatus = 'done';
        // 当前页数小于总页数 设置状态为done
        if (ProxyObject.page < ProxyObject.pages) {
          ProxyObject.dataStatus = 'load-more';
        }
        // 当前页数大于等于总页数 设置状态为no-more
        if (ProxyObject.page >= ProxyObject.pages && ProxyObject.pages != 0) {
          ProxyObject.dataStatus = 'no-more';
        }
        // 首页加载时 获取的数据列表内容长度为0 则设置状态为empty
        if (ProxyObject.pages == 0) {
          ProxyObject.dataStatus = 'empty';
        }
        return ProxyObject;
      },

    },
  }
</script>

<style lang="scss" scoped>
  .comments-container {
    margin-bottom: 100rpx;
    background-color: #ffffff;
    padding: 48rpx 32rpx;
    box-sizing: border-box;
    padding-bottom: 180rpx;
    box-sizing: border-box;

    .comments-num {
      font-size: 30rpx;
      font-weight: 500;
      margin: 6rpx 0 26rpx 0;
    }

    // 评论块 因主频率与子评论同样的样式
    .comment-container {
      display: flex;
      margin-bottom: 16rpx;

      // 用户头像
      .left-container {
        padding-right: 16rpx;

        .user-avatar {
          width: 80rpx;
          height: 80rpx;
          border-radius: 50%;
        }
      }

      .right-container {
        display: flex;
        flex-direction: column;
        width: calc(100% - 96rpx);
        padding-top: 8rpx;

        .head-container {
          display: flex;
          align-items: center;
          justify-content: space-between;

          .user-info-container {
            display: flex;
            align-items: center;
            font-size: 28rpx;

            .author {
              padding: 0 16rpx;
              height: 28rpx;
              font-size: 20rpx;
              line-height: 28rpx;
              text-align: center;
              background-color: #3FD3D1;
              color: #fff;
              margin-left: 10rpx;
              border-radius: 2rpx;
              box-sizing: border-box;
            }
          }

          .like-container {
            display: flex;
            align-items: center;
            color: #7A7A7A;
            font-size: 28rpx;

            .like-num {
              margin-left: 8rpx;
            }
          }
        }

        // 评论内容区域
        .comment-contet-container {
          font-size: 28rpx;
          line-height: 42rpx;
          color: #505050;
          word-wrap: break-word;
          padding: 16rpx 0;

          .user-name {
            color: #3fd3d1;
            padding: 0 8rpx;
          }
        }

        .comment-date-container {
          line-height: 42rpx;

          text:nth-child(1) {
            font-size: 28rpx;
            color: #cccccc;
            margin-right: 32rpx;
          }

          text:nth-child(2) {
            font-size: 28rpx;
            color: #545454;
          }

        }
      }
    }

    .main-comments {}


    .child-comments {
      padding-left: 96rpx;

      .left-container .user-avatar {
        width: 60rpx;
        height: 60rpx;
      }

      .right-container {
        width: calc(100% - 56rpx);
      }

    }



    .more-comment {
      height: 70rpx;
      display: flex;
      align-items: center;
      color: #666;
      font-size: 26rpx;
      margin-left: 80rpx;

      .divider {
        width: 48rpx;
        height: 0rpx;
        border-bottom: 2rpx solid #666;
        margin-right: 16rpx;
      }

      .icon {
        margin-left: 8rpx;
        transform: rotateZ(-90deg);
      }
    }

    .more-comment-expand {
      .icon {
        transform: rotateZ(90deg);
      }
    }


    // 加载更多状态区域
    .status-container {
      width: 100%;
      line-height: 130rpx;
      text-align: center;
      font-size: 28rpx;
      color: #CCCCCC;
    }

    // 评论发布区域
    .comments-post-container {
      width: 100%;
      max-width: 750px;
      background-color: #EEF2F4;
      position: fixed;
      bottom: 0;
      left: var(--window-left);
      display: flex;
      align-items: center;
      justify-content: space-between;
      z-index: 999;
      transition: bottom 0.1s ease;
      padding: 24rpx 32rpx;
      box-sizing: border-box;

      .left-container {
        padding-right: 28rpx;
        box-sizing: border-box;
        width: calc(100% - 72rpx);

        .input-container {
          width: 100%;
          height: 72rpx;
          border: #3FD3D1 2rpx solid;
          box-sizing: border-box;
          border-radius: 50rpx;
          background-color: #fff;
          font-size: 28rpx;

          input {
            height: 72rpx;
            line-height: 72rpx;
            padding: 0 30rpx;
          }
        }

      }

      .right-container {
        .post-btn {
          width: 72rpx;
          height: 72rpx;
          background-color: #3FD3D1;
          color: #FFFFFF;
          border-radius: 50%;
          font-size: 26rpx;
          text-align: center;
          line-height: 72rpx;
        }
      }
    }

  }

  .more-open-container {
    display: flex;
    justify-content: space-between;
    align-items: center;
  }
</style>